package midend.IR_Instruction;

import midend.IR_Type.IR_Type;
import midend.IR_Type.IR_Void;
import midend.IR_Value.IR_BaseBlock;
import midend.IR_Value.IR_FuncBlock;
import midend.IR_Value.IR_Local_Value;
import midend.IR_Value.IR_Value;

import java.util.ArrayList;
import java.util.List;

public class Call_Instruction extends Instruction{
    private IR_FuncBlock funcBlock;
    private List<IR_Value> params;
    private int number;
    private static int counter = 0;

    public IR_FuncBlock get_funcBlock() {
        return funcBlock;
    }

    public List<IR_Value> get_params() {
        return params;
    }

    public Call_Instruction(List<IR_Value> op, IR_BaseBlock bb) {
        super(op, bb);
        //传递的op里面就是一个参数  函数块
        this.funcBlock = (IR_FuncBlock) op.get(1);
        params = new ArrayList<IR_Value>();
        for(int i = 2; i < op.size();i++) {
            params.add(op.get(i));
            addValue(op.get(i));
        }
        this.number = counter++;
    }

    public void updateop(int index, IR_Value newValue) {
        set_Op(index + 2, newValue);
        params.set(index, newValue);
    }

    public void setParams(int k, IR_Value new_param) {
        params.set(k, new_param);
        set_Op(k + 2, new_param);
    }


    @Override
    public String toString() {
        //op[ret,funcblock,params...]
        IR_Value ans = get_op().get(0);
        StringBuilder s = new StringBuilder();
        if(!(this.funcBlock.get_RetType() instanceof IR_Void)) {
            s.append(ans.get_ValueName()).append(" = ");
        }
        s.append( "call ")
                .append(this.funcBlock.get_RetType().get_TypeName()).append(" ")
                .append(this.funcBlock.get_ValueName()).append("(");
        int z = 0;
        for(IR_Value para:this.params){
            if(z >= 1){
                s.append(", ");
            }
            z++;
            s.append(para.get_Type().get_TypeName()).append(" ").append(para.get_ValueName());
        }
        s.append(")");
        return  s.toString();

    }


    @Override
    public Call_Instruction clone(IR_BaseBlock block) {
        String copy_name = ((IR_Local_Value) get_op().get(0)).get_Local_Identity();
        IR_Type copy_type = get_op().get(0).get_Type();
        IR_Value res = new IR_Local_Value(copy_name, copy_type);
        ArrayList<IR_Value> copy_ops = new ArrayList<>();
        copy_ops.add(res);
        for (int i = 1 ; i< get_op().size() ; i++) {
            IR_Value copy_op  = get_op().get(i);
            if(IR_FuncBlock.cloneMap_Value.containsKey(copy_op)) {
                copy_op = IR_FuncBlock.cloneMap_Value.get(copy_op);
            }
            copy_ops.add(copy_op);
        }
        Call_Instruction copy_ins = new Call_Instruction(copy_ops, block);
        return copy_ins;
    }
}
